import java.io.IOException;
import java.util.HashMap;
import java.util.Vector;

public class BowSenseFeature {
  private String senseid_;
  private String instanceId_;
  Vector<String> words_;
  Vector<Integer> senseFeatureV_;
  HashMap<String, Integer> wordCounts_;
  
  BowSenseFeature(String senseid, String instanceId, Vector<String> words) {
    words_ = new Vector<String>();
    words_.addAll(words);
    
    senseid_ = senseid;
    instanceId_ = instanceId;
    
    senseFeatureV_ = new Vector<Integer>();
    wordCounts_ = new HashMap<String, Integer>();
  }
  
  public void processFeatureVector(Vector<String> featureVector) {
    wordCounts_.clear();
    for (int i = 0; i < words_.size(); ++i) {
      Integer c = wordCounts_.get(words_.get(i));
      
      if (c == null) {
        wordCounts_.put(words_.get(i), 1);
      } else {
        wordCounts_.put(words_.get(i), c + 1);
      }
    }
    
    for (int i = 0; i < featureVector.size(); ++i) {
      Integer c = wordCounts_.get(featureVector.get(i));
      
      if (c == null)
        senseFeatureV_.add(0);
      else {
        senseFeatureV_.add(c);
      }
    }
  }
  
  public double getNorm() {
    double norm = 0.0;
    
    for (int i = 0; i < senseFeatureV_.size(); ++i) {
      norm += (double)(senseFeatureV_.get(i) * senseFeatureV_.get(i)); 
    }
    
    return Math.sqrt(norm);
  }
  
  public String getSense() {
    return senseid_;
  }
  
  public Vector<Integer> getSenseFeatureVector() {
    return senseFeatureV_;
  }
  
  public double getCosineSimilarity(BowSenseFeature testFeature) {
    double sim = 0.0;
    
    Vector<Integer> testFeatureV = testFeature.getSenseFeatureVector();
    if (testFeatureV.size() != senseFeatureV_.size()) {
      System.err.println("Feature vector lenght should be same in test and train.");
    }

    for (int i = 0; i < senseFeatureV_.size(); ++i) {
      sim += testFeatureV.get(i) * senseFeatureV_.get(i);      
    }
    
    sim /= getNorm();
    sim /= testFeature.getNorm();
    
    return sim;
  }
  
  public double getWeightedSimilarity(BowSenseFeature testFeature, BowFeatureVector bfv) {
    double sim = 0.0;
    
    Vector<Integer> testFeatureV = testFeature.getSenseFeatureVector();
    if (testFeatureV.size() != senseFeatureV_.size()) {
      System.err.println("Feature vector lenght should be same in test and train.");
    }

    for (int i = 0; i < senseFeatureV_.size(); ++i) {
      if (testFeatureV.get(i) > 0 && senseFeatureV_.get(i) > 0) {
        sim += bfv.getFeatureWeight(i);
      }
    }
    
    sim /= testFeatureV.size();
    
    return sim;
  }
  
  public double getBinarySimilarity(BowSenseFeature testFeature) {
    double sim = 0.0;
    
    Vector<Integer> testFeatureV = testFeature.getSenseFeatureVector();
    if (testFeatureV.size() != senseFeatureV_.size()) {
      System.err.println("Feature vector lenght should be same in test and train.");
    }
    
    for (int i = 0; i < senseFeatureV_.size(); ++i) {
      if (testFeatureV.get(i) > 0 && senseFeatureV_.get(i) > 0) {
        sim += 1.0;      
      }
    }
    
    sim /= testFeatureV.size();
    
    return sim;
  }
  
  public void writeToCSV(String lexelt) {
    String str = "";
    
    str += lexelt + ",";
    str += instanceId_ + ",";
    for (int i = 0; i < senseFeatureV_.size(); ++i) {
      if (senseFeatureV_.get(i) > 0)
        str += "1,";
      else
        str += "0,";
    }
    try {
      if (senseid_.equals("UNKNOWN")) {
        WSD.testCSV.write(str + "\n");
      } else {
        str += senseid_;
        WSD.trainCSV.write(str + "\n");
      }
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
